//-----------------------------------------------------------------------
// <copyright file="Regex.cs" company="Rhys Parry">
//    Copyright Rhys Parry 2008
//    This file is released under the Apache 2.0 License
// </copyright>
//-----------------------------------------------------------------------
namespace Smarts.Core.RegularExpressions
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text.RegularExpressions;
    using Stre = System.Text.RegularExpressions;

    /// <summary>
    /// Represents an immutable regular expression.
    /// </summary>
    public class Regex
    {
        private readonly Stre.Regex _regex;

        /// <summary>
        /// Initializes a new instance of the <see cref="Regex"/> class.
        /// </summary>
        /// <param name="pattern">The pattern.</param>
        public Regex(string pattern)
        {
            _regex = new Stre.Regex(pattern);
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="Regex"/> class.
        /// </summary>
        /// <param name="pattern">The pattern.</param>
        /// <param name="options">The options.</param>
        public Regex(string pattern, RegexOptions options)
        {
            _regex = new Stre.Regex(pattern, (Stre.RegexOptions) options);
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="Regex"/> class.
        /// </summary>
        /// <param name="regex">The regex.</param>
        private Regex(Stre.Regex regex)
        {
            _regex = regex;
        }

        /// <summary>
        /// Gets or sets the size of the cache.
        /// </summary>
        /// <value>The size of the cache.</value>
        public static int CacheSize
        {
            get
            {
                return Stre.Regex.CacheSize;
            }
            
            set
            {
                Stre.Regex.CacheSize = value;
            }
        }

        /// <summary>
        /// Gets the options.
        /// </summary>
        /// <value>The options.</value>
        public RegexOptions Options
        {
            get
            {
                return (RegexOptions) _regex.Options;
            }
        }

        public bool RightToLeft
        {
            get
            {
                return _regex.RightToLeft;
            }
        }

        public static string Escape(string str)
        {
            return Stre.Regex.Escape(str);
        }

        public static bool IsMatch(string input, string pattern)
        {
            return Stre.Regex.IsMatch(input, pattern);
        }

        public static bool IsMatch(string input, string pattern, RegexOptions options)
        {
            return Stre.Regex.IsMatch(input, pattern, (Stre.RegexOptions) options);
        }

        public static Match Match(string input, string pattern)
        {
            return Stre.Regex.Match(input, pattern);
        }

        public static Match Match(string input, string pattern, RegexOptions options)
        {
            return Stre.Regex.Match(input, pattern, (Stre.RegexOptions) options);
        }

        public static IEnumerable<Match> Matches(string input, string pattern)
        {
            return Stre.Regex.Matches(input, pattern).Cast<Match>();
        }

        public static IEnumerable<Match> Matches(string input, string pattern, RegexOptions options)
        {
            return Stre.Regex.Matches(input, pattern, (Stre.RegexOptions) options).Cast<Match>();
        }

        public static string Replace(string input, string pattern, string replacement)
        {
            return Stre.Regex.Replace(input, pattern, replacement);
        }

        public static string Replace(string input, string pattern, Func<Match, string> evaluator)
        {
            return Stre.Regex.Replace(input, pattern, ToMatchEvaluator(evaluator));
        }

        public static string Replace(string input, string pattern, string replacement, RegexOptions options)
        {
            return Stre.Regex.Replace(input, pattern, replacement, (Stre.RegexOptions) options);
        }

        public static string Replace(string input, string pattern, Func<Match, string> evaluator, RegexOptions options)
        {
            return Stre.Regex.Replace(input, pattern, ToMatchEvaluator(evaluator), (Stre.RegexOptions) options);
        }

        public static string[] Split(string input, string pattern)
        {
            return Stre.Regex.Split(input, pattern);
        }

        public static string[] Split(string input, string pattern, RegexOptions options)
        {
            return Stre.Regex.Split(input, pattern, (Stre.RegexOptions) options);
        }

        public static string Unescape(string str)
        {
            return Stre.Regex.Unescape(str);
        }

        public string[] GetGroupNames()
        {
            return _regex.GetGroupNames();
        }

        public int[] GetGroupNumbers()
        {
            return _regex.GetGroupNumbers();
        }

        public string GroupNameFromNumber(int i)
        {
            return _regex.GroupNameFromNumber(i);
        }

        public int GroupNumberFromName(string name)
        {
            return _regex.GroupNumberFromName(name);
        }

        public bool IsMatch(string input)
        {
            return _regex.IsMatch(input);
        }

        public bool IsMatch(string input, int startAt)
        {
            return _regex.IsMatch(input, startAt);
        }

        public Match Match(string input)
        {
            return _regex.Match(input);
        }

        public Match Match(string input, int startAt)
        {
            return _regex.Match(input, startAt);
        }

        public Match Match(string input, int beginning, int length)
        {
            return _regex.Match(input, beginning, length);
        }

        public IEnumerable<Match> Matches(string input)
        {
            return _regex.Matches(input).Cast<Match>();
        }

        public IEnumerable<Match> Matches(string input, int startAt)
        {
            return _regex.Matches(input, startAt).Cast<Match>();
        }

        public string Replace(string input, string replacement)
        {
            return _regex.Replace(input, replacement);
        }

        public string Replace(string input, Func<Match, string> evaluator)
        {
            return _regex.Replace(input, ToMatchEvaluator(evaluator));
        }

        public string Replace(string input, string replacement, int count)
        {
            return _regex.Replace(input, replacement, count);
        }

        public string Replace(string input, Func<Match, string> evaluator, int count)
        {
            return _regex.Replace(input, ToMatchEvaluator(evaluator), count);
        }

        public string Replace(string input, string replacement, int count, int startAt)
        {
            return _regex.Replace(input, replacement, count, startAt);
        }

        public string Replace(string input, Func<Match, string> evaluator, int count, int startAt)
        {
            return _regex.Replace(input, ToMatchEvaluator(evaluator), count, startAt);
        }

        public string[] Split(string input)
        {
            return _regex.Split(input);
        }

        public string[] Split(string input, int count)
        {
            return _regex.Split(input, count);
        }

        public string[] Split(string input, int count, int startAt)
        {
            return _regex.Split(input, count, startAt);
        }

        public override string ToString()
        {
            return _regex.ToString();
        }

        public static implicit operator Stre.Regex(Regex regex)
        {
            return regex._regex;
        }

        public static implicit operator Regex(Stre.Regex regex)
        {
            return new Regex(regex);
        }

        private static MatchEvaluator ToMatchEvaluator(Func<Match, string> evaluator)
        {
            return match => evaluator.Invoke(match);
        }
    }
}